package routers

import (
	"encoding/json"
	"net/http"

	"gitee.com/kessil/chicory/internal/config"
	"gitee.com/kessil/chicory/internal/middleware"
	"gitee.com/kessil/chicory/internal/models"
	"gitee.com/kessil/chicory/internal/repositories"
	"gitee.com/kessil/chicory/internal/utils"

	"github.com/go-chi/chi/v5"
	"xorm.io/xorm"
)

type RoleRouter struct {
	*GenericCRUDRouter[models.Role]
	db   *xorm.Engine
	cfg  *config.Config
	repo *repositories.RoleRepository
}

func NewRoleRouter(db *xorm.Engine, cfg *config.Config) *RoleRouter {
	// 定义允许筛选的字段
	allowedFields := []string{"name", "enable"}

	genericRouter := NewGenericCRUDRouter[models.Role](db, cfg, "role", allowedFields)

	return &RoleRouter{
		GenericCRUDRouter: genericRouter,
		db:                db,
		cfg:               cfg,
		repo:              repositories.NewRoleRepository(db),
	}
}

func (rr *RoleRouter) Routes() chi.Router {
	r := chi.NewRouter()

	r.Use(middleware.JWTAuthMiddleware(rr.cfg))

	// 继承泛型CRUD路由（已经包含分页和查询中间件）
	r.Mount("/", rr.GenericCRUDRouter.Routes())

	// 添加角色特有的路由
	r.With(middleware.PaginationMiddleware(rr.cfg), middleware.QueryMiddleware(rr.allowedFields)).Get("/page", rr.page)
	r.Get("/", rr.all)
	r.Get("/permissions/tree", rr.tree)
	r.With(middleware.IDParamMiddleware("roleId")).Patch("/users/add/{roleId}", rr.add)
	r.With(middleware.IDParamMiddleware("roleId")).Patch("/users/remove/{roleId}", rr.remove)

	return r
}

// all 列表查询（使用中间件处理的筛选）
func (rr *RoleRouter) all(w http.ResponseWriter, r *http.Request) {
	// 从中间件获取筛选条件
	filters := middleware.GetQueryFiltersFromContext(r)

	// 执行查询
	var items []models.Role
	var err error

	if len(filters) > 0 {
		// 使用带筛选的查询
		items, err = rr.repo.GetAllWithFilters(filters)
	} else {
		// 使用普通查询
		items, _, err = rr.repo.GetAll(nil)
	}

	if err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to get "+rr.resource)
		return
	}

	middleware.JSONSuccess(w, items)
}

func (rr *RoleRouter) page(w http.ResponseWriter, r *http.Request) {
	pageNo, pageSize := middleware.GetPaginationFromContext(r)

	filters := middleware.GetQueryFiltersFromContext(r)

	res, err := rr.repo.ListRolesWithPermissions(filters, pageNo, pageSize)
	if err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to get roles")
		return
	}

	middleware.JSONSuccess(w, res)
}

func (rr *RoleRouter) tree(w http.ResponseWriter, r *http.Request) {
	// claims, ok := middleware.GetClaimsFromContext(r, "claims")
	pr := repositories.NewPermissionRepository(rr.db)
	perms, err := pr.GetAllPermissionTree()
	if err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Faild to query permissions tree by roleIds")
		return
	}
	middleware.JSONSuccess(w, perms)
}

type ReqUserIds struct {
	UserIds []int64 `json:"userIds"`
}

func (rr *RoleRouter) add(w http.ResponseWriter, r *http.Request) {
	roleId := middleware.GetIDFromContext(r, "roleId")

	var item ReqUserIds
	if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
		utils.Error(err.Error())
		middleware.JSONError(w, http.StatusBadRequest, "Invalid request")
		return
	}
	if err := rr.repo.BatchAddUsersRole(roleId, item.UserIds); err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Faild to batch add users's role")
	}
	middleware.JSONSuccess(w, nil)
}

func (rr *RoleRouter) remove(w http.ResponseWriter, r *http.Request) {
	roleId := middleware.GetIDFromContext(r, "roleId")

	var item ReqUserIds
	if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
		utils.Error(err.Error())
		middleware.JSONError(w, http.StatusBadRequest, "Invalid request")
		return
	}
	if err := rr.repo.BatchRemoveUsersRole(roleId, item.UserIds); err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Faild to batch add users's role")
	}
	middleware.JSONSuccess(w, nil)
}
